/**
 * 抖音开放平台集成服务
 * 提供用户登录、内容发布、数据抓取和粉丝同步等功能
 */

import { get, post } from '@/utils/request';
import { handleError } from '@/utils/errorHandler';
import { cache } from '@/utils/cacheManager';

// 抖音用户信息接口
interface DouyinUser {
  open_id: string;
  union_id: string;
  nickname: string;
  avatar: string;
  gender: number; // 0-未知 1-男 2-女
  country: string;
  province: string;
  city: string;
  follower_count: number;
  following_count: number;
  aweme_count: number; // 作品数
}

// 抖音视频信息接口
interface DouyinVideo {
  item_id: string;
  title: string;
  desc: string;
  cover: string;
  video_url: string;
  duration: number;
  create_time: number;
  statistics: {
    digg_count: number; // 点赞数
    comment_count: number; // 评论数
    share_count: number; // 分享数
    play_count: number; // 播放数
  };
  author: DouyinUser;
}

// 发布视频参数接口
interface PublishVideoParams {
  video_url: string;
  text?: string;
  micro_app_id?: string;
  micro_app_title?: string;
  micro_app_url?: string;
  poi_id?: string;
  poi_name?: string;
  game_id?: string;
  game_content?: string;
}

// 抖音API响应接口
interface DouyinApiResponse<T = any> {
  error_code: number;
  description: string;
  data: T;
}

// 粉丝数据接口
interface FansData {
  date: string;
  new_fans: number;
  cancel_fans: number;
  active_fans: number;
  total_fans: number;
}

// 数据分析接口
interface VideoAnalytics {
  item_id: string;
  date: string;
  play_count: number;
  like_count: number;
  comment_count: number;
  share_count: number;
  profile_view: number;
  follow_count: number;
}

/**
 * 抖音开放平台服务类
 */
class DouyinService {
  private readonly baseUrl = 'https://open.douyin.com';
  private readonly clientKey: string;
  private readonly clientSecret: string;
  private accessToken: string = '';
  private refreshToken: string = '';
  
  constructor() {
    this.clientKey = process.env.DOUYIN_CLIENT_KEY || '';
    this.clientSecret = process.env.DOUYIN_CLIENT_SECRET || '';
    this.loadTokens();
  }
  
  /**
   * 加载存储的token
   */
  private loadTokens(): void {
    try {
      const tokens = cache.get('douyin_tokens', 'local') as any;
      if (tokens) {
        this.accessToken = tokens.access_token || '';
        this.refreshToken = tokens.refresh_token || '';
      }
    } catch (error) {
      console.warn('Failed to load douyin tokens:', error);
    }
  }
  
  /**
   * 保存token到本地存储
   */
  private saveTokens(accessToken: string, refreshToken: string): void {
    try {
      this.accessToken = accessToken;
      this.refreshToken = refreshToken;
      cache.set('douyin_tokens', {
        access_token: accessToken,
        refresh_token: refreshToken
      }, {
        storage: 'local',
        expireTime: 24 * 60 * 60 * 1000 // 24小时
      });
    } catch (error) {
      console.error('Failed to save douyin tokens:', error);
    }
  }
  
  /**
   * 生成授权登录URL
   */
  generateAuthUrl(redirectUri: string, state?: string): string {
    const params = new URLSearchParams({
      client_key: this.clientKey,
      response_type: 'code',
      scope: 'user_info,video.list,video.data,video.upload,fans.data',
      redirect_uri: redirectUri,
      state: state || Date.now().toString()
    });
    
    return `${this.baseUrl}/platform/oauth/connect/?${params.toString()}`;
  }
  
  /**
   * 通过授权码获取访问令牌
   */
  async getAccessToken(code: string): Promise<{ access_token: string; refresh_token: string }> {
    try {
      const response = await post('/api/douyin/oauth/access_token', {
        client_key: this.clientKey,
        client_secret: this.clientSecret,
        code: code,
        grant_type: 'authorization_code'
      });
      
      if (response.data.error_code === 0) {
        const { access_token, refresh_token } = response.data.data;
        this.saveTokens(access_token, refresh_token);
        return { access_token, refresh_token };
      } else {
        throw new Error(response.data.description);
      }
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 刷新访问令牌
   */
  async refreshAccessToken(): Promise<string> {
    try {
      const response = await post('/api/douyin/oauth/refresh_token', {
        client_key: this.clientKey,
        refresh_token: this.refreshToken,
        grant_type: 'refresh_token'
      });
      
      if (response.data.error_code === 0) {
        const { access_token, refresh_token } = response.data.data;
        this.saveTokens(access_token, refresh_token);
        return access_token;
      } else {
        throw new Error(response.data.description);
      }
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 获取用户信息
   */
  async getUserInfo(openId?: string): Promise<DouyinUser> {
    try {
      const cacheKey = `douyin_user_${openId || 'current'}`;
      
      return await cache.getOrSet(
        cacheKey,
        async () => {
          const response = await get('/api/douyin/oauth/userinfo', {
            access_token: this.accessToken,
            open_id: openId
          });
          
          if (response.data.error_code === 0) {
            return response.data.data;
          } else {
            throw new Error(response.data.description);
          }
        },
        {
          storage: 'local',
          expireTime: 30 * 60 * 1000 // 30分钟
        }
      );
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 获取用户视频列表
   */
  async getUserVideos(openId: string, cursor: number = 0, count: number = 10): Promise<{
    list: DouyinVideo[];
    cursor: number;
    has_more: boolean;
  }> {
    try {
      const response = await get('/api/douyin/video/list', {
        access_token: this.accessToken,
        open_id: openId,
        cursor: cursor,
        count: count
      });
      
      if (response.data.error_code === 0) {
        return response.data.data;
      } else {
        throw new Error(response.data.description);
      }
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 发布视频到抖音
   */
  async publishVideo(params: PublishVideoParams): Promise<{ item_id: string }> {
    try {
      const response = await post('/api/douyin/video/upload', {
        access_token: this.accessToken,
        ...params
      });
      
      if (response.data.error_code === 0) {
        return response.data.data;
      } else {
        throw new Error(response.data.description);
      }
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 获取视频数据分析
   */
  async getVideoAnalytics(itemIds: string[], dateType: 'yesterday' | '7days' | '30days' = '7days'): Promise<VideoAnalytics[]> {
    try {
      const cacheKey = `douyin_analytics_${itemIds.join(',')}_${dateType}`;
      
      return await cache.getOrSet(
        cacheKey,
        async () => {
          const response = await post('/api/douyin/data/external/item', {
            access_token: this.accessToken,
            item_ids: itemIds,
            date_type: dateType
          });
          
          if (response.data.error_code === 0) {
            return response.data.data.result_list || [];
          } else {
            throw new Error(response.data.description);
          }
        },
        {
          storage: 'local',
          expireTime: 60 * 60 * 1000 // 1小时
        }
      );
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 获取粉丝数据
   */
  async getFansData(dateType: 'yesterday' | '7days' | '30days' = '7days'): Promise<FansData[]> {
    try {
      const cacheKey = `douyin_fans_${dateType}`;
      
      return await cache.getOrSet(
        cacheKey,
        async () => {
          const response = await post('/api/douyin/data/external/fans_profile', {
            access_token: this.accessToken,
            date_type: dateType
          });
          
          if (response.data.error_code === 0) {
            return response.data.data.result_list || [];
          } else {
            throw new Error(response.data.description);
          }
        },
        {
          storage: 'local',
          expireTime: 2 * 60 * 60 * 1000 // 2小时
        }
      );
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 搜索热门视频
   */
  async searchHotVideos(keyword: string, cursor: number = 0, count: number = 10): Promise<{
    list: DouyinVideo[];
    cursor: number;
    has_more: boolean;
  }> {
    try {
      const cacheKey = `douyin_search_${keyword}_${cursor}_${count}`;
      
      return await cache.getOrSet(
        cacheKey,
        async () => {
          const response = await get('/api/douyin/discovery/ent/rank/item', {
            access_token: this.accessToken,
            keyword: keyword,
            cursor: cursor,
            count: count
          });
          
          if (response.data.error_code === 0) {
            return response.data.data;
          } else {
            throw new Error(response.data.description);
          }
        },
        {
          storage: 'local',
          expireTime: 15 * 60 * 1000 // 15分钟
        }
      );
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 获取热门话题
   */
  async getHotTopics(): Promise<Array<{
    challenge_id: string;
    challenge_name: string;
    desc: string;
    user_count: number;
    view_count: number;
  }>> {
    try {
      const cacheKey = 'douyin_hot_topics';
      
      return await cache.getOrSet(
        cacheKey,
        async () => {
          const response = await get('/api/douyin/discovery/ent/rank/challenge', {
            access_token: this.accessToken
          });
          
          if (response.data.error_code === 0) {
            return response.data.data.list || [];
          } else {
            throw new Error(response.data.description);
          }
        },
        {
          storage: 'local',
          expireTime: 60 * 60 * 1000 // 1小时
        }
      );
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 同步用户数据到本地数据库
   */
  async syncUserData(openId: string): Promise<void> {
    try {
      const userInfo = await this.getUserInfo(openId);
      const videos = await this.getUserVideos(openId, 0, 50);
      const fansData = await this.getFansData('30days');
      
      // 同步到本地数据库
      await post('/api/douyin/sync/user', {
        user_info: userInfo,
        videos: videos.list,
        fans_data: fansData
      });
      
      console.log('Douyin user data synced successfully');
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
  
  /**
   * 批量发布内容到抖音
   */
  async batchPublish(contents: Array<{
    video_url: string;
    text: string;
    schedule_time?: number;
  }>): Promise<Array<{ item_id: string; success: boolean; error?: string }>> {
    const results = [];
    
    for (const content of contents) {
      try {
        if (content.schedule_time && content.schedule_time > Date.now()) {
          // 定时发布
          await this.schedulePublish(content, content.schedule_time);
          results.push({ item_id: '', success: true });
        } else {
          // 立即发布
          const result = await this.publishVideo({
            video_url: content.video_url,
            text: content.text
          });
          results.push({ item_id: result.item_id, success: true });
        }
      } catch (error) {
        results.push({ 
          item_id: '', 
          success: false, 
          error: error instanceof Error ? error.message : 'Unknown error'
        });
      }
    }
    
    return results;
  }
  
  /**
   * 定时发布内容
   */
  private async schedulePublish(content: {
    video_url: string;
    text: string;
  }, scheduleTime: number): Promise<void> {
    // 将定时发布任务存储到队列中
    await post('/api/douyin/schedule', {
      content: content,
      schedule_time: scheduleTime,
      access_token: this.accessToken
    });
  }
  
  /**
   * 检查token是否有效
   */
  async checkTokenValid(): Promise<boolean> {
    try {
      await this.getUserInfo();
      return true;
    } catch (error) {
      // 尝试刷新token
      try {
        await this.refreshAccessToken();
        return true;
      } catch (refreshError) {
        return false;
      }
    }
  }
  
  /**
   * 获取账号统计数据
   */
  async getAccountStats(): Promise<{
    follower_count: number;
    following_count: number;
    aweme_count: number;
    total_favorited: number;
  }> {
    try {
      const userInfo = await this.getUserInfo();
      const videos = await this.getUserVideos(userInfo.open_id, 0, 100);
      
      const totalFavorited = videos.list.reduce((sum, video) => {
        return sum + video.statistics.digg_count;
      }, 0);
      
      return {
        follower_count: userInfo.follower_count,
        following_count: userInfo.following_count,
        aweme_count: userInfo.aweme_count,
        total_favorited: totalFavorited
      };
    } catch (error) {
      handleError(error, {
        showToast: true,
        logToConsole: true
      });
      throw error;
    }
  }
}

// 创建单例实例
const douyinService = new DouyinService();

// 导出服务实例和便捷方法
export { douyinService, DouyinService };
export type { DouyinUser, DouyinVideo, PublishVideoParams, FansData, VideoAnalytics };

// 便捷方法导出
export const {
  generateAuthUrl,
  getAccessToken,
  getUserInfo,
  getUserVideos,
  publishVideo,
  getVideoAnalytics,
  getFansData,
  searchHotVideos,
  getHotTopics,
  syncUserData,
  batchPublish,
  checkTokenValid,
  getAccountStats
} = douyinService;

export default douyinService;